package org.example.common.express;

import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * QLExpress 管理器
 */
@Slf4j
@Component
public class QLExpressManager implements InitializingBean, ApplicationContextAware {

    private ExpressRunner runner;
    private ApplicationContext applicationContext;

    public Object execute(String statement, Map<String, Object> context) throws Exception {
        IExpressContext<String, Object> expressContext = new QLExpressContext(context != null ? context : new HashMap<>(), applicationContext);
        return runner.execute(statement, expressContext, null, true, false);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        runner = new ExpressRunner(false, false);
        runner.addOperatorWithAlias("大于", ">", null);
        runner.addOperatorWithAlias("小于", "<", null);
        runner.addOperatorWithAlias("等于", "==", null);
        runner.addOperatorWithAlias("大于等于", ">=", null);
        runner.addOperatorWithAlias("小于等于", "<=", null);

        Map<String, RuleHandler> beanMap = applicationContext.getBeansOfType(RuleHandler.class);
        beanMap.values().forEach(bean -> {
            Method[] methods = bean.getClass().getDeclaredMethods();
            for (Method method : methods) {
                try {
                    QlRule qlRule = method.getAnnotation(QlRule.class);
                    if (qlRule == null) continue;
                    runner.addFunctionOfClassMethod(UUID.randomUUID().toString(), bean.getClass(), method.getName(), method.getParameterTypes(), null);
                } catch (Exception ex) {
                    log.error("runner.addFunctionOfClassMethod", ex);
                }
            }
        });
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}